package com.ruoyi.system.service;

import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.S3Exception;
import software.amazon.awssdk.auth.credentials.AwsBasicCredentials;
import software.amazon.awssdk.auth.credentials.StaticCredentialsProvider;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.URI;
import java.net.URL;
import java.net.URLEncoder;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Service
public class MarkdownService {

    private static final Logger logger = LoggerFactory.getLogger(MarkdownService.class);
    private static final Pattern IMAGE_PATTERN = Pattern.compile("!\\[.*?\\]\\((.*?)\\)");

    // 处理Markdown文件，将图片链接替换为S3存储桶中的链接
    public void processMarkdown(String endpoint, String accessKey, String secretKey, String bucketName, String markdownFilePath) throws IOException {
        try (S3Client s3Client = createS3Client(endpoint, accessKey, secretKey)) {
            // 读取Markdown文件内容
            String content = new String(Files.readAllBytes(Paths.get(markdownFilePath)));
            Matcher matcher = IMAGE_PATTERN.matcher(content);
            StringBuffer updatedContent = new StringBuffer();

            // 查找所有的图片链接并进行处理
            while (matcher.find()) {
                String img = matcher.group(1);
                String newUrl = processImage(img, s3Client, bucketName);
                String decodedUrl = URLDecoder.decode(newUrl, StandardCharsets.UTF_8.name());
                matcher.appendReplacement(updatedContent, Matcher.quoteReplacement("![](" + decodedUrl + ")"));
            }
            matcher.appendTail(updatedContent);

            // 将更新后的内容写回Markdown文件
            Files.write(Paths.get(markdownFilePath), updatedContent.toString().getBytes());
            logger.info("Markdown文件处理并保存成功。");
        }
    }

    // 创建S3客户端，用于与S3进行交互
    private S3Client createS3Client(String endpoint, String accessKey, String secretKey) {
        return S3Client.builder()
                .endpointOverride(URI.create(endpoint))
                .region(Region.of("us-west-2")) // 设置适当的区域
                .credentialsProvider(StaticCredentialsProvider.create(AwsBasicCredentials.create(accessKey, secretKey)))
                .build();
    }

    // 处理图片，将其上传到S3存储桶并返回新的URL
    private String processImage(String img, S3Client s3Client, String bucketName) throws IOException {
        String imageFileName = getImageFileName(img);

        // 如果图片已经上传到存储桶，则直接返回现有的URL
        if (img.startsWith("http") && img.contains(bucketName)) {
            logger.info("图片 {} 已经上传，使用现有URL。", img);
            return img;
        }

        // 下载图片并上传到S3存储桶
        File file = downloadImage(img);

        try {
            PutObjectRequest putObjectRequest = PutObjectRequest.builder()
                    .bucket(bucketName)
                    .key(imageFileName)
                    .build();

            s3Client.putObject(putObjectRequest, RequestBody.fromFile(file));
            logger.info("将图片 {} 上传到S3", imageFileName);

            // 获取上传后的图片URL
            String url = s3Client.utilities().getUrl(builder -> builder.bucket(bucketName).key(imageFileName)).toString();
            return url;
        } catch (S3Exception e) {
            logger.error("上传图片 {} 失败: {}", imageFileName, e.getMessage(), e);
            throw new IOException("上传图片到S3失败: " + e.getMessage(), e);
        } finally {
            // 删除临时文件
            if (file.getName().startsWith("temp") && !file.delete()) {
                logger.warn("删除临时文件失败: {}", file.getAbsolutePath());
            }
        }
    }

    // 下载图片文件，支持远程和本地图片
    private File downloadImage(String img) throws IOException {
        if (img.startsWith("http")) {
            // 下载远程图片
            logger.info("正在下载远程图片: {}", img);
            try {
                URL imageUrl = new URL(img);
                File tempFile = File.createTempFile("temp", ".tmp");
                try (InputStream inputStream = imageUrl.openStream()) {
                    Files.copy(inputStream, tempFile.toPath(), java.nio.file.StandardCopyOption.REPLACE_EXISTING);
                    logger.info("成功下载远程图片: {}", img);
                    return tempFile;
                }
            } catch (Exception e) {
                logger.error("URL格式错误或下载图片失败: {}", img);
                throw new IOException("URL格式错误或下载图片失败: " + img, e);
            }
        } else if (img.startsWith("file:///")) {
            // 处理本地文件路径
            String localPath = img.substring(8);
            File file = new File(localPath);
            if (file.exists()) {
                logger.info("正在处理本地图片: {}", localPath);
                return file;
            } else {
                logger.error("本地文件未找到: {}", localPath);
                throw new FileNotFoundException("文件不存在: " + localPath);
            }
        } else {
            // 直接处理相对或绝对路径的本地文件
            File file = new File(img);
            if (file.exists()) {
                logger.info("正在处理本地图片: {}", img);
                return file;
            } else {
                logger.error("本地文件未找到: {}", img);
                throw new FileNotFoundException("文件不存在: " + img);
            }
        }
    }

    // 获取图片文件名
    private String getImageFileName(String img) throws UnsupportedEncodingException {
        try {
            if (img.startsWith("http")) {
                // 如果是远程图片，解析URL并提取文件名
                String decodedUrl = URLDecoder.decode(img, StandardCharsets.UTF_8.name());
                return new File(new URL(decodedUrl).getPath()).getName();
            } else {
                // 如果是本地图片，直接提取文件名
                return new File(img).getName();
            }
        } catch (Exception e) {
            logger.error("提取文件名时URL格式错误: {}", img);
            throw new IllegalArgumentException("提取文件名时URL格式错误: " + img, e);
        }
    }
}
